package com.yeyks.commonReference.service.hotel.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.ImmutableMap;
import com.yeyks.account.dal.domain.AccountInfo;
import com.yeyks.common.base.Arguments;
import com.yeyks.common.constants.AccountType;
import com.yeyks.common.em.accountinfo.AccountInfoTypeEnum;
import com.yeyks.common.exception.ServiceException;
import com.yeyks.commonReference.service.hotel.HotelAccountBillService;
import com.yeyks.commonReference.service.hotel.HotelAccountOverviewService;
import com.yeyks.commonReference.service.hotel.HotelInfoService;
import com.yeyks.hotel.dal.dao.HotelAccountOverviewMapper;
import com.yeyks.hotel.dal.domain.HotelAccountBill;
import com.yeyks.hotel.dal.domain.HotelAccountOverview;
import com.yeyks.hotel.dal.domain.HotelInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Map;

/**
 * 酒店账户总览表 服务实现类
 *
 * @author shuai
 * @date 2019-07-08
 */
@Service
public class HotelAccountOverviewServiceImpl extends ServiceImpl<HotelAccountOverviewMapper, HotelAccountOverview> implements HotelAccountOverviewService {

    @Autowired
    private HotelAccountBillService hotelAccountBillService;
    @Autowired
    private HotelInfoService hotelInfoService;

    /**
     * 根据酒店的id查询该酒店的账户信息，没有创建
     *
     * @param hotelId
     * @return
     */
    @Override
    public HotelAccountOverview selectByHotelId(Integer hotelId) {
        if (hotelId == null) {
            return null;
        }
        HotelAccountOverview overview = baseMapper.selectOne(new QueryWrapper<HotelAccountOverview>().eq(HotelAccountOverview.HOTEL_ID, hotelId));
        if (overview != null) {
            return overview;
        }
        return getHotelAccountOverview(null, hotelId, AccountInfoTypeEnum.HotelManager.value());
    }

    /**
     * 根据账户id查询该账户信息，没有创建
     *
     * @param accountId
     * @return
     */
    @Override
    public HotelAccountOverview selectByAccountId(Integer accountId, Integer accountType) {
        Arguments.intIsNull(accountId, "账户id不能为空");
        HotelAccountOverview overview = baseMapper.selectOne(new QueryWrapper<HotelAccountOverview>()
                .eq(HotelAccountOverview.ACCOUNT_ID, accountId)
                .eq(HotelAccountOverview.ACCOUNT_TYPE, accountType)
                .last("limit 1"));
        if (overview != null) {
            return overview;
        }
        return getHotelAccountOverview(accountId, null, accountType);
    }

    private HotelAccountOverview getHotelAccountOverview(Integer accountId, Integer hotelId, Integer accountType) {
        HotelAccountOverview overview = new HotelAccountOverview();
        overview.setAccountId(accountId);
        overview.setAccountType(accountType);
        overview.setHotelId(hotelId);
        overview.setTotalInAmount(0);
        overview.setTotalFeeAmount(0);
        overview.setRemainAmount(0);
        overview.setOutAmount(0);
        Date date = new Date();
        overview.setUpdateTime(date);
        overview.setCreateTime(date);
        if (baseMapper.insert(overview) == 1) {
            return overview;
        }
        return null;
    }

    /**
     * 账户总览表减少(提现)
     *
     * @param accountId      账户id
     * @param operatorAmount 操作金额
     * @param orderNo        订单号
     * @param accountType    账户类型
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean descAccount(Integer accountId, Integer operatorAmount, String orderNo, Integer accountType) {
        Arguments.intIsNull(operatorAmount, "提现金额不能为空");
        Arguments.intEqualZero(operatorAmount, "提现金额不能为0");
        Arguments.intLtZero(operatorAmount, "提现金额有误");
        HotelAccountOverview overview = selectByAccountId(accountId, accountType);
        if (overview.getRemainAmount() == null || overview.getRemainAmount() < operatorAmount) {
            throw new ServiceException("余额不足");
        }
        if (!operatorAmount.equals(overview.getRemainAmount())) {
            throw new ServiceException("必须全部提现");
        }
        Date date = new Date();
        //首先修改账户总览表的数据
        overview.setOutAmount(overview.getOutAmount() + operatorAmount);
        overview.setRemainAmount(overview.getRemainAmount() - operatorAmount);
        overview.setUpdateTime(date);
        if (baseMapper.updateById(overview) != 1) {
            throw new ServiceException("修改账户表异常");
        }
        //写入账户明细表信息
        HotelAccountBill bill = new HotelAccountBill();
        bill.setCreateTime(date);
        bill.setAccountId(accountId);
        bill.setAccountType(accountType);
        bill.setRemark(HotelAccountBill.Remark.SUCCESS.desc());
        bill.setType(HotelAccountBill.Type.OUT.value());
        bill.setOperatorAmount(operatorAmount);
        bill.setBizNo(orderNo);
        if (!hotelAccountBillService.save(bill)) {
            throw new ServiceException("插入账户明细异常");
        }
        return true;
    }

    /**
     * 账户总览表增加(提现驳回)
     *
     * @param orderNo 提现订单号
     * @param remark  备注
     * @return
     */
    @Override
    public Boolean addAccount(String orderNo, String remark) {
        HotelAccountBill accountBill = hotelAccountBillService.getOne(new QueryWrapper<HotelAccountBill>().eq(HotelAccountBill.BIZ_NO, orderNo).eq(HotelAccountBill.TYPE, HotelAccountBill.Type.OUT.value()).eq(HotelAccountBill.REMARK, HotelAccountBill.Remark.SUCCESS.desc()));
        if (accountBill == null) {
            throw new ServiceException("该提现订单不存在");
        }
//        HotelAccountOverview overview = baseMapper.selectOne(new QueryWrapper<HotelAccountOverview>().eq(HotelAccountOverview.ACCOUNT_ID, accountBill.getAccountId()));
        HotelAccountOverview overview = selectByAccountId(accountBill.getAccountId(), accountBill.getAccountType());
        if (overview == null) {
            throw new ServiceException("该账户不存在");
        }
        Date date = new Date();
        //首先修改账户总览表的数据
        overview.setOutAmount(overview.getOutAmount() - accountBill.getOperatorAmount());
        overview.setRemainAmount(overview.getRemainAmount() + accountBill.getOperatorAmount());
        overview.setUpdateTime(date);
        if (baseMapper.updateById(overview) != 1) {
            throw new ServiceException("修改账户表异常");
        }
        //写入账户明细表信息
        HotelAccountBill bill = new HotelAccountBill();
        bill.setCreateTime(date);
        bill.setHotelId(accountBill.getHotelId());
        bill.setAccountId(accountBill.getAccountId());
        bill.setAccountType(accountBill.getAccountType());
        bill.setRemark(remark);
        bill.setType(HotelAccountBill.Type.IN.value());
        bill.setOperatorAmount(accountBill.getOperatorAmount());
        bill.setBizNo(orderNo);
        if (!hotelAccountBillService.save(bill)) {
            throw new ServiceException("插入账户明细异常");
        }
        return null;
    }

    /**
     * 获取酒店账户余额
     *
     * @param loginUser
     * @return
     */
    @Override
    public Map<String, Object> remain(AccountInfo loginUser) {
        if (AccountType.HotelManager != loginUser.getType()) {
            throw new ServiceException("您无权访问");
        }
        HotelInfo hotelInfo = hotelInfoService.getHotelInfoAccountHotelInfo(loginUser);
        HotelAccountOverview overview = selectByHotelId(hotelInfo.getId());
        if (null == overview) {
            throw new ServiceException("该账户下酒店不存在");
        }
        return ImmutableMap.of("remain", overview.getRemainAmount(), "phone", hotelInfo.getPhone());
    }

}
